﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LinqToLfsWorld.Extensions;
using System.Xml.Linq;

namespace LinqToLfsWorld.Queries
{
	/// <summary>
	/// Queries host information from LfsWorld
	/// </summary>
	public class HostsQuery : LfsWorldQuery<Host>
	{

		/// <summary>
		/// Initializes a new instance of the <see cref="HostsQuery"/> class.
		/// </summary>
		/// <param name="context">The context.</param>
		public HostsQuery(LfsWorldContext context)
			: base(context)
		{
		}

		/// <summary>
		/// Gets the URL used to query LfsWorld.
		/// </summary>
		protected override string GetUrl()
		{
			return LfsHelper.GetPubstatUrlBase(PubstatResponseType.Xml, this, "hosts");	
		}

		/// <summary>
		/// Gets the entities given LfsWorld response XML
		/// </summary>
		/// <param name="responseData">The response data.</param>
		/// <returns>A collection of Host entities</returns>
		protected override IEnumerable<Host> ProcessResponse(string responseData)
		{
			XDocument doc = XDocument.Parse(responseData);

			foreach (XElement node in doc.Descendants("entry"))
			{
				Host host = new Host();

				host.HostName = node.Element("hostname").Value.StripLfsColours();

				ParseTMLT(node, host);
				ParseTCRM(node, host);
				ParseLaps(node, host);

				host.CarFlags = (CarFlags)Convert.ToInt32(node.Element("cars").Value);
				host.RuleFlags = (RuleFlags)Convert.ToInt32(node.Element("rules").Value);
				host.QualifyingMinutes = Convert.ToByte(node.Element("qualmins").Value);
				host.Country = node.Element("country").Value;
				host.RacerCount = Convert.ToByte(node.Element("nrracers").Value);

				ParseRacers(node, host);

				yield return host;
			}

		}

		private static void ParseRacers(XElement node, Host host)
		{
			XElement racersNode = node.Element("racers_array");
			List<string> racers = new List<string>(host.RacerCount);

			var q = from r in racersNode.Elements()
					select r;

			foreach (var elem in q)
			{
				racers.Add(elem.Value);
			}

			host.RacerNames = racers.ToArray();
		}

		private static void ParseLaps(XElement node, Host host)
		{
			if (node.Element("laps").Value != "")
			{
				byte laps = Convert.ToByte(node.Element("laps").Value);

				if (laps == 0)
				{
					host.SessionMode = HostSessionMode.Practice;
				}
				else if (laps > 0 && laps <= 100)
				{
					host.Laps = laps;
					host.SessionMode = HostSessionMode.Laps;
				}
				else if (laps > 100 && laps <= 190)
				{
					laps = (byte)(100 + (laps - 100) * 10);
					host.SessionMode = HostSessionMode.Laps;
				}
				else
				{
					host.Hours = (byte)(laps - 190);
					host.SessionMode = HostSessionMode.Time;
				}
			}
		}

		private static void ParseTCRM(XElement node, Host host)
		{
			XElement tcrm = node.Element("tcrm");
			host.TrackIdent = string.Empty;

			host.TrackIdent += tcrm.Element("track").Value;
			host.TrackIdent += tcrm.Element("config").Value;
			host.TrackIdent += tcrm.Element("reverse").Value;

			host.TrackName = Utility.CircuitNameFactory.GetNameFromIdent(host.TrackIdent);

			host.MaxPlayers = Convert.ToByte(tcrm.Element("maxconn").Value);
		}

		private static void ParseTMLT(XElement node, Host host)
		{
			XElement tmlt = node.Element("tmlt");
			host.Type = (HostType)Convert.ToByte(tmlt.Element("type").Value);
			host.Version = tmlt.Element("main").Value + tmlt.Element("letter").Value;
			host.TestId = Convert.ToByte(tmlt.Element("testid").Value);
		}

	}
}
